#ifndef UDP_SOCKET_SERVER
#define UDP_SOCKET_SERVER

#include "threads.h"
#include "udpMessageQueue.h"
#include "udp.h"
#include "IPv6Address.h"
#include <vector>
#include <map>
#include <string>

void * udpSocketServerListener( void * data );

const int RANDOM_PORT = -1;
const int PORT_IN_USE = -1;
const int PORT_NOT_ALLOCATED = -2;
const int PORT_NOT_LEGAL = -3;

class UDPSocketServer
{
	public:
		UDPSocketServer(const std::string ports, const std::string listenAddress = "::" );
		~UDPSocketServer();
		//void registerThread(const int &port, UDPMessageQueue &queue );
		int registerThread( UDPMessageQueue *queue );
		void unregisterThread( const int &threadid );
		int requestSocket( const int &threadid, const int &port = RANDOM_PORT ); //returns port num, port = -1 means a random port
		void releaseSocket( const uint16_t &port );
		//void unregisterThread();
		void sendData( const UDPMessage &message );
		void runListener();
		//void runSender();
		void setIntelMessageQueue( UDPMessageQueue* queue );

	private:
		std::vector<std::string>& split(const std::string &s, char delim, std::vector<std::string> &elems);
		int createSocket( const uint16_t &port );
		void printError();
		uint16_t randomPort();
	
	private:
		//After construction sockets should be read only
		std::map< uint16_t, int > sockets_; //key: port, data: socket
		Mutex messageQueueMutex_; 
		std::vector< UDPMessageQueue* > messageQueues_;
		Mutex registrationMutex_;
		std::map< uint16_t, int > registrations_; //key: port. data: threadIDs
    //UDPMessageQueue sendQueue_;
		UDPMessageQueue* intelMessageQueue_;
		std::string listenAddress_;
};


#endif
